use crate::src::struct_and_type::{
    ListCompareFunc, ListEntry, ListEqualFunc, ListIterator, ListValue,
};

extern "C" {
    fn malloc(_: u64) -> *mut ();
    fn free(_: *mut ());
}
#[no_mangle]
pub extern "C" fn list_free(mut list: *mut ListEntry) {
    let mut entry: *mut ListEntry = 0 as *mut ListEntry;
    entry = list;
    while !entry.is_null() {
        let mut next: *mut ListEntry = 0 as *mut ListEntry;
        next = unsafe { (*entry).next };
        (unsafe { free(entry as *mut ()) });
        entry = next;
    }
}
#[no_mangle]
pub extern "C" fn list_prepend(
    mut list: *mut *mut ListEntry,
    mut data: ListValue,
) -> *mut ListEntry {
    let mut newentry: *mut ListEntry = 0 as *mut ListEntry;
    if list.is_null() {
        return 0 as *mut ListEntry;
    }
    newentry = (unsafe { malloc(::core::mem::size_of::<ListEntry>() as u64) }) as *mut ListEntry;
    if newentry.is_null() {
        return 0 as *mut ListEntry;
    }
    (unsafe { (*newentry).data = data });
    if !(unsafe { *list }).is_null() {
        (unsafe { (**list).prev = newentry });
    }
    (unsafe { (*newentry).prev = 0 as *mut ListEntry });
    (unsafe { (*newentry).next = *list });
    (unsafe { *list = newentry });
    return newentry;
}
#[no_mangle]
pub extern "C" fn list_append(
    mut list: *mut *mut ListEntry,
    mut data: ListValue,
) -> *mut ListEntry {
    let mut rover: *mut ListEntry = 0 as *mut ListEntry;
    let mut newentry: *mut ListEntry = 0 as *mut ListEntry;
    if list.is_null() {
        return 0 as *mut ListEntry;
    }
    newentry = (unsafe { malloc(::core::mem::size_of::<ListEntry>() as u64) }) as *mut ListEntry;
    if newentry.is_null() {
        return 0 as *mut ListEntry;
    }
    (unsafe { (*newentry).data = data });
    (unsafe { (*newentry).next = 0 as *mut ListEntry });
    if (unsafe { *list }).is_null() {
        (unsafe { *list = newentry });
        (unsafe { (*newentry).prev = 0 as *mut ListEntry });
    } else {
        rover = unsafe { *list };
        while !(unsafe { (*rover).next }).is_null() {
            rover = unsafe { (*rover).next };
        }
        (unsafe { (*newentry).prev = rover });
        (unsafe { (*rover).next = newentry });
    }
    return newentry;
}
#[no_mangle]
pub extern "C" fn list_data(mut listentry: *mut ListEntry) -> ListValue {
    if listentry.is_null() {
        return core::ptr::null_mut();
    }
    return unsafe { (*listentry).data };
}
#[no_mangle]
pub extern "C" fn list_set_data(mut listentry: *mut ListEntry, mut value: ListValue) {
    if !listentry.is_null() {
        (unsafe { (*listentry).data = value });
    }
}
#[no_mangle]
pub extern "C" fn list_prev(mut listentry: *mut ListEntry) -> *mut ListEntry {
    if listentry.is_null() {
        return 0 as *mut ListEntry;
    }
    return unsafe { (*listentry).prev };
}
#[no_mangle]
pub extern "C" fn list_next(mut listentry: *mut ListEntry) -> *mut ListEntry {
    if listentry.is_null() {
        return 0 as *mut ListEntry;
    }
    return unsafe { (*listentry).next };
}
#[no_mangle]
pub extern "C" fn list_nth_entry(mut list: *mut ListEntry, mut n: u32) -> *mut ListEntry {
    let mut entry: *mut ListEntry = 0 as *mut ListEntry;
    let mut i: u32 = 0;
    entry = list;
    i = 0 as u32;
    while i < n {
        if entry.is_null() {
            return 0 as *mut ListEntry;
        }
        entry = unsafe { (*entry).next };
        i = i.wrapping_add(1);
        i;
    }
    return entry;
}
#[no_mangle]
pub extern "C" fn list_nth_data(mut list: *mut ListEntry, mut n: u32) -> ListValue {
    let mut entry: *mut ListEntry = 0 as *mut ListEntry;
    entry = list_nth_entry(list, n);
    if entry.is_null() {
        return core::ptr::null_mut();
    } else {
        return unsafe { (*entry).data };
    };
}
#[no_mangle]
pub extern "C" fn list_length(mut list: *mut ListEntry) -> u32 {
    let mut entry: *mut ListEntry = 0 as *mut ListEntry;
    let mut length: u32 = 0;
    length = 0 as u32;
    entry = list;
    while !entry.is_null() {
        length = length.wrapping_add(1);
        length;
        entry = unsafe { (*entry).next };
    }
    return length;
}
#[no_mangle]
pub extern "C" fn list_to_array(mut list: *mut ListEntry) -> *mut ListValue {
    let mut rover: *mut ListEntry = 0 as *mut ListEntry;
    let mut array: *mut ListValue = 0 as *mut ListValue;
    let mut length: u32 = 0;
    let mut i: u32 = 0;
    length = list_length(list);
    array = (unsafe {
        malloc((::core::mem::size_of::<ListValue>() as u64).wrapping_mul(length as u64))
    }) as *mut ListValue;
    if array.is_null() {
        return 0 as *mut ListValue;
    }
    rover = list;
    i = 0 as u32;
    while i < length {
        let fresh0 = unsafe { &mut (*array.offset(i as isize)) };
        *fresh0 = unsafe { (*rover).data };
        rover = unsafe { (*rover).next };
        i = i.wrapping_add(1);
        i;
    }
    return array;
}
#[no_mangle]
pub extern "C" fn list_remove_entry(
    mut list: *mut *mut ListEntry,
    mut entry: *mut ListEntry,
) -> i32 {
    if list.is_null() || (unsafe { *list }).is_null() || entry.is_null() {
        return 0;
    }
    if (unsafe { (*entry).prev }).is_null() {
        (unsafe { *list = (*entry).next });
        if !(unsafe { (*entry).next }).is_null() {
            (unsafe { (*(*entry).next).prev = 0 as *mut ListEntry });
        }
    } else {
        (unsafe { (*(*entry).prev).next = (*entry).next });
        if !(unsafe { (*entry).next }).is_null() {
            (unsafe { (*(*entry).next).prev = (*entry).prev });
        }
    }
    (unsafe { free(entry as *mut ()) });
    return 1;
}
#[no_mangle]
pub extern "C" fn list_remove_data(
    mut list: *mut *mut ListEntry,
    mut callback: ListEqualFunc,
    mut data: ListValue,
) -> u32 {
    let mut entries_removed: u32 = 0;
    let mut rover: *mut ListEntry = 0 as *mut ListEntry;
    let mut next: *mut ListEntry = 0 as *mut ListEntry;
    if list.is_null() || callback.is_none() {
        return 0 as u32;
    }
    entries_removed = 0 as u32;
    rover = unsafe { *list };
    while !rover.is_null() {
        next = unsafe { (*rover).next };
        if (unsafe { callback.expect("non-null function pointer")((*rover).data, data) }) != 0 {
            if (unsafe { (*rover).prev }).is_null() {
                (unsafe { *list = (*rover).next });
            } else {
                (unsafe { (*(*rover).prev).next = (*rover).next });
            }
            if !(unsafe { (*rover).next }).is_null() {
                (unsafe { (*(*rover).next).prev = (*rover).prev });
            }
            (unsafe { free(rover as *mut ()) });
            entries_removed = entries_removed.wrapping_add(1);
            entries_removed;
        }
        rover = next;
    }
    return entries_removed;
}
extern "C" fn list_sort_internal(
    mut list: *mut *mut ListEntry,
    mut compare_func: ListCompareFunc,
) -> *mut ListEntry {
    let mut pivot: *mut ListEntry = 0 as *mut ListEntry;
    let mut rover: *mut ListEntry = 0 as *mut ListEntry;
    let mut less_list: *mut ListEntry = 0 as *mut ListEntry;
    let mut more_list: *mut ListEntry = 0 as *mut ListEntry;
    let mut less_list_end: *mut ListEntry = 0 as *mut ListEntry;
    let mut more_list_end: *mut ListEntry = 0 as *mut ListEntry;
    if list.is_null() || compare_func.is_none() {
        return 0 as *mut ListEntry;
    }
    if (unsafe { *list }).is_null() || (unsafe { (**list).next }).is_null() {
        return unsafe { *list };
    }
    pivot = unsafe { *list };
    less_list = 0 as *mut ListEntry;
    more_list = 0 as *mut ListEntry;
    rover = unsafe { (**list).next };
    while !rover.is_null() {
        let mut next: *mut ListEntry = unsafe { (*rover).next };
        if (unsafe {
            compare_func.expect("non-null function pointer")((*rover).data, (*pivot).data)
        }) < 0
        {
            (unsafe { (*rover).prev = 0 as *mut ListEntry });
            (unsafe { (*rover).next = less_list });
            if !less_list.is_null() {
                (unsafe { (*less_list).prev = rover });
            }
            less_list = rover;
        } else {
            (unsafe { (*rover).prev = 0 as *mut ListEntry });
            (unsafe { (*rover).next = more_list });
            if !more_list.is_null() {
                (unsafe { (*more_list).prev = rover });
            }
            more_list = rover;
        }
        rover = next;
    }
    less_list_end = list_sort_internal(&mut less_list, compare_func);
    more_list_end = list_sort_internal(&mut more_list, compare_func);
    (unsafe { *list = less_list });
    if less_list.is_null() {
        (unsafe { (*pivot).prev = 0 as *mut ListEntry });
        (unsafe { *list = pivot });
    } else {
        (unsafe { (*pivot).prev = less_list_end });
        (unsafe { (*less_list_end).next = pivot });
    }
    (unsafe { (*pivot).next = more_list });
    if !more_list.is_null() {
        (unsafe { (*more_list).prev = pivot });
    }
    if more_list.is_null() {
        return pivot;
    } else {
        return more_list_end;
    };
}
#[no_mangle]
pub extern "C" fn list_sort(mut list: *mut *mut ListEntry, mut compare_func: ListCompareFunc) {
    list_sort_internal(list, compare_func);
}
#[no_mangle]
pub extern "C" fn list_find_data(
    mut list: *mut ListEntry,
    mut callback: ListEqualFunc,
    mut data: ListValue,
) -> *mut ListEntry {
    let mut rover: *mut ListEntry = 0 as *mut ListEntry;
    rover = list;
    while !rover.is_null() {
        if (unsafe { callback.expect("non-null function pointer")((*rover).data, data) })
            != 0
        {
            return rover;
        }
        rover = unsafe { (*rover).next };
    }
    return 0 as *mut ListEntry;
}
#[no_mangle]
pub extern "C" fn list_iterate(mut list: *mut *mut ListEntry, mut iter: *mut ListIterator) {
    (unsafe { (*iter).prev_next = list });
    (unsafe { (*iter).current = 0 as *mut ListEntry });
}
#[no_mangle]
pub extern "C" fn list_iter_has_more(mut iter: *mut ListIterator) -> i32 {
    if (unsafe { (*iter).current }).is_null()
        || (unsafe { (*iter).current }) != (unsafe { *(*iter).prev_next })
    {
        return ((unsafe { *(*iter).prev_next }) != core::ptr::null_mut() as *mut ListEntry)
            as i32;
    } else {
        return ((unsafe { (*(*iter).current).next }) != core::ptr::null_mut() as *mut ListEntry)
            as i32;
    };
}
#[no_mangle]
pub extern "C" fn list_iter_next(mut iter: *mut ListIterator) -> ListValue {
    if (unsafe { (*iter).current }).is_null()
        || (unsafe { (*iter).current }) != (unsafe { *(*iter).prev_next })
    {
        (unsafe { (*iter).current = *(*iter).prev_next });
    } else {
        (unsafe { (*iter).prev_next = &mut (*(*iter).current).next });
        (unsafe { (*iter).current = (*(*iter).current).next });
    }
    if (unsafe { (*iter).current }).is_null() {
        return core::ptr::null_mut();
    } else {
        return unsafe { (*(*iter).current).data };
    };
}
#[no_mangle]
pub extern "C" fn list_iter_remove(mut iter: *mut ListIterator) {
    if !((unsafe { (*iter).current }).is_null()
        || (unsafe { (*iter).current }) != (unsafe { *(*iter).prev_next }))
    {
        (unsafe { *(*iter).prev_next = (*(*iter).current).next });
        if !(unsafe { (*(*iter).current).next }).is_null() {
            (unsafe { (*(*(*iter).current).next).prev = (*(*iter).current).prev });
        }
        (unsafe { free((*iter).current as *mut ()) });
        (unsafe { (*iter).current = 0 as *mut ListEntry });
    }
}
